/* 
 * Copyright 2008 Rodrigo Reyes <reyes.rr at gmail dot com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License. You may
 * obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * permissions and limitations under the License.
**/
package net.kornr.canvaschart.client.core;

import net.kornr.abstractcanvas.client.ICanvasExt;
import net.kornr.canvaschart.client.xy.XYDataSet;

public class CoordinateSystem 
{
	private double m_top, m_left, m_width, m_height;
	// private IGWTCanvasExt m_canvas;
	
	private double m_coordminx = Double.MAX_VALUE;
	private double m_coordmaxx = 0;
	private double m_coordminy = Double.MAX_VALUE;
	private double m_coordmaxy = 0;

	private double m_coordwidth;
	private double m_coordheight;
	
	public CoordinateSystem()
	{
	}
	
	public CoordinateSystem(ICanvasExt canvas, double leftOffset, double topOffset, double width, double height)
	{
//		m_canvas = canvas;
//		m_top = topOffset;
//		m_left = leftOffset;
//		m_width = width;
//		m_height = height;
	}
	
	public boolean isPrepared()
	{
		return m_coordminx < m_coordmaxx;
	}
	
	/**
	 * Specify the offsets in the target canvas
	 * @param leftOffset offset from the left side
	 * @param topOffset offset from the top
	 * @param width width of the canvas
	 * @param height height of the canvas
	 */
	public void setCanvasOffsets(double leftOffset, double topOffset, double width, double height)
	{
		m_top = topOffset;
		m_left = leftOffset;
		m_width = width;
		m_height = height;		
	}
	
	public void prepare(XYDataSet ds)
	{
		for (int j=0; j<ds.size(); j++)
		{
			Point p = ds.get(j);
			prepareCoords(p);
		}
		m_coordwidth = m_coordmaxx - m_coordminx;
		m_coordheight = m_coordmaxy - m_coordminy;
	}

	protected void prepareCoords(Point p)
	{
		double x = p.getX();
		double y = p.getY();
		
		if (x>m_coordmaxx)
			m_coordmaxx = x;
		if (y>m_coordmaxy)
			m_coordmaxy = y;		
		if (x < m_coordminx)
			m_coordminx = x;
		if (y < m_coordminy)
			m_coordminy = y;
	}

	public void addVerticalBorder()
	{
		m_coordminy -= (m_coordmaxy-m_coordminy)/10;
		m_coordmaxy += (m_coordmaxy-m_coordminy)/10;
		
		m_coordwidth = m_coordmaxx - m_coordminx;
		m_coordheight = m_coordmaxy - m_coordminy;
	}

	public double getCoordWidth()
	{
		return m_coordwidth;
	}
	
	public double getCoordHeight()
	{
		return m_coordheight;
	}

	public double getCoordMinX()
	{
		return m_coordminx;
	}
	public double getCoordMinY()
	{
		return m_coordminy;
	}
	public double getCoordMaxX()
	{
		return m_coordmaxx;
	}
	public double getCoordMaxY()
	{
		return m_coordmaxy;
	}	
	
	/**
	 * Convert Data Coordinates (from the dataset) into pixel coordinates (on the canvas)
	 * @param datax
	 * @param datay
	 * @return a Point object
	 */
	public Point getCoord(double datax, double datay)
	{
		double locx = (m_width * ((datax- m_coordminx)/m_coordwidth));
		double locy = m_height - m_height*((datay - m_coordminy)/m_coordheight);
		return new Point(m_left+locx, m_top+locy);
	}

	/**
	 * Convert Data Coordinates (from the dataset) into pixel coordinates (on the canvas)
	 * @param datax
	 * @param datay
	 * @return a Point object
	 */
	public Point getCoord(Point p)
	{
		return getCoord(p.getX(), p.getY());
	}

	
	public Point getDataCoord(int x, int y)
	{
		// x = (m_width * ((dx-m_coordminx)/m_coordwidth));
		// x/m_width = (dx-m_coordminx)/m_coordwidth
		// (x/m_width) * m_coordwidth = dx - m_coordminx
		// ((x/m_width) * m_coordwidth) + m_coordminx = dx
		
		double dx = (((double)(x-m_left)/m_width) * m_coordwidth) + m_coordminx;
		
		// y = m_height - m_height*((dy - m_coordminy)/m_coordheight);
		// y - m_height = m_height*((dy - m_coordminy)/m_coordheight);
		// (y-m_height)/m_height = (dy - m_coordminy)/m_coordheight;
		// ((y-m_height)/m_height)*m_coordheight = (dy - m_coordminy)
		// ((y-m_height)/m_height)*m_coordheight + m_coordminy = dy
		double dy = -(((y-m_top)-m_height)/m_height)*m_coordheight + m_coordminy;
		
		return new Point(dx,dy);
	}
	
	public Point getTopLeft()
	{
		return new Point(m_left, m_top);		
	}
	public Point getTopRight()
	{
		return new Point(m_left+m_width, m_top);		
	}
	public Point getBottomLeft()
	{
		return new Point(m_left, m_top+m_height);		
	}
	public Point getBottomRight()
	{
		return new Point(m_left+m_width, m_top+m_height);		
	}
	
}
